# -*- coding: utf-8 -*-
# created on 2016/5/12


from mathsolver.functions.base import *
from mathsolver.functions.basic import Filter
from sympy import solve_univariate_inequality, reduce_inequalities, solveset
from mathsolver.functions.sympy_utils import simplify_ineq_solveset
from sympy.abc import x
from mathsolver.functions.fangcheng.yici import YiCi005
from mathsolver.functions.fangcheng.base import yicifangcheng_judge


class FangChenBuDengShi001(BaseFunction):
    """
    解不等式
    """
    def solver(self, *args):
        f1, op, f2 = args[0].sympify()
        symbols = (f1 - f2).free_symbols
        sym_value = self.searchs(symbols)
        if sym_value:
            return Filter().solver(BaseSymbolValue(sym_value), args[0])

        ineq = Rel(f1, f2, op)
        free_symbols = ineq.free_symbols
        if len(set(free_symbols)) == 1:
            symbol = free_symbols.pop()

            answer = solve_univariate_inequality(ineq, symbol, relational=False)
            if not f1.is_Symbol:
                self.steps.append(["解得：", self.output_answer({symbol: answer})])
                self.label.add("解不等式")
        else:
            symbol = default_symbol(f1 - f2, args)
            new_ineq = reduce_inequalities(Rel(f1, f2, op), symbol)
            new_ineq = simplify_ineq_solveset(new_ineq)
            if new_ineq.args[0] != symbol:
                new_ineq = new_ineq.reversed

            if new_ineq.rel_op == ">":
                answer = Interval(new_ineq.args[1], S.Infinity, True, True)
            elif new_ineq.rel_op == ">=":
                answer = Interval(new_ineq.args[1], S.Infinity, False, True)
            elif new_ineq.rel_op == "<":
                answer = Interval(-S.Infinity, new_ineq.args[1], True, True)
            elif new_ineq.rel_op == "<=":
                answer = Interval(-S.Infinity, new_ineq.args[1], True, False)

        self.output.append(BaseSymbolValue({symbol: answer}))
        return self


class FangChenBuDengShi002(BaseFunction):
    """
    解不等式组
    """
    def solver(self, *args):
        if not args[0].ineqs:
            ineqs1 = args[0].value[0]
            ineqs = [BaseIneq([ineqs1[0], ineqs1[1], ineqs1[2]]), BaseIneq([ineqs1[2], ineqs1[3], ineqs1[4]])]
            symbols = set()
            for ineq in ineqs:
                expr = ineq.sympify()
                symbols.update((expr[2] - expr[0]).free_symbols)
        else:
            ineqs = args[0].ineqs
            symbols = args[0].free_symbols()
        solve_sets = dict([(sym, S.Reals) for sym in symbols])
        for i, ineq in enumerate(ineqs, 1):
            if len(ineq.free_symbols()) > 1:
                self.output.append(args[0])
                return self

            if isinstance(ineq, BaseIneq):
                expr = ineq.sympify()[0] - ineq.sympify()[2]
                symbol = default_symbol(expr, args)
                answer = FangChenBuDengShi001().solver(ineq, BaseVariable(symbol)).output[0].value[symbol]
                solve_sets[symbol] = solve_sets[symbol].intersect(answer)

            elif isinstance(ineq, BaseEq):
                f1, f2 = ineq.sympify()
                symbol = default_symbol(f1 - f2, args)
                answer = solveset(f1 - f2, symbol, S.Reals)
                if len(answer) == 1 and str(answer).find("log") >= 0:
                    # 若(x+\\dfrac{1}{x})^n展开式的二项式系数之和为64,求n
                    answer.args[0] = simplify(answer.args[0])
                solve_sets[symbol] = solve_sets[symbol].intersect(answer)
            else:
                raise ValueError("unvalid type %s" % type(ineq))

            self.steps.append(["由(%d)得" % i, self.output_answer({symbol: answer})])

        symbol_value = BaseSymbolValue(solve_sets)
        self.steps.append(["所以，不等式组的解集为：", symbol_value.printing()])
        self.output.append(BaseSymbolValue(solve_sets))
        self.label.add("解不等式组")
        return self


class FangChenBuDengShi003(BaseFunction):
    """
    含参一元一次不等式组无解问题
    """
    def solver(self, *args):
        ineqs = args[0].sympify()
        symbol = x
        answers = []
        small = None
        large = None
        left_op = None
        right_op = None
        for i, ineq in enumerate(ineqs, 1):
            res = jiebudengshi_Parameter().solver(BaseIneq(ineq)).output[0]
            answer = res.value[symbol]
            answers.append(answer)
            self.steps.append(["由(%d)得" % i, self.output_answer({symbol: answer})])
            l, r, lopen, ropen = answer.args
            smaller_op = {False: "<=", True: "<"}
            larger_op = {False: ">=", True: ">"}
            if l.is_infinite:
                large = r
                right_op = smaller_op[ropen]
            else:
                small = l
                left_op = larger_op[lopen]
        assert small is not None and large is not None
        assert left_op is not None and right_op is not None
        if "=" in left_op and "=" in right_op:
            ineq = Rel(small, large, ">")
            ineq_output = [small, ">", large]
        else:
            ineq = Rel(small, large, ">=")
            ineq_output = [small, ">=", large]

        self.steps.append(["因为不等式组无解，所以：", new_latex(ineq)])
        self.output.append(BaseIneq(ineq_output))
        self.label.add("含参一元一次不等式组无解问题")
        return self


class FangChenBuDengShi004(BaseFunction):
    """
    根据含参的一元一次不等式组的解集求参
    """
    def solver(self, *args):
        ineqs = args[0].sympify()
        if len(args[1].value) == 5:
            symbol = default_symbol(ineqs[0][0] - ineqs[0][2])
            solutions_value = args[1].value
            solutions_left = sympify(solutions_value[0])
            solutions_right = sympify(solutions_value[4])
            if "=" in solutions_value[1]:
                solutions_lopen = False
            else:
                solutions_lopen = True
            if "=" in solutions_value[3]:
                solutions_ropen = False
            else:
                solutions_ropen = True
            answers = []
            answer_max = 0
            answer_min = 0
            for i, ineq in enumerate(ineqs, 1):
                res = jiebudengshi_Parameter().solver(BaseIneq(ineq)).output[0]
                answer = res.value[symbol]
                answer_left, answer_right, answer_lopen, answer_ropen = answer.args
                if answer_left.is_infinite and not answer_right.is_infinite:
                    answer_max = answer_right
                else:
                    answer_min = answer_left
                answers.append(answer)
                self.steps.append(["由(%d)得" % i, self.output_answer({symbol: answer})])
            self.steps.append(["", "因为不等式的解集是 %s %s %s %s %s" % (new_latex(sympify(solutions_value[0])),
                                                                          new_latex(solutions_value[1]),
                                                                          new_latex(sympify(solutions_value[2])),
                                                                          new_latex(solutions_value[3]),
                                                                          new_latex(sympify(solutions_value[4])))])
            if answer_min == solutions_left and answer_max != solutions_right:
                eq = [answer_max, solutions_right]
                self.output.append(BaseEq(eq))
                self.steps.append(["所以", BaseEq(eq).printing()])
            elif answer_min != solutions_left and answer_max == solutions_right:
                eq = [answer_min, solutions_left]
                self.output.append(BaseEq(eq))
                self.steps.append(["所以", BaseEq(eq).printing()])
            else:
                eqs = [[answer_max, solutions_right], [answer_min, solutions_left]]
                self.output.append(BaseEqs(eqs))
                self.steps.append(["所以", BaseEqs(eqs).printing()])
        else:
            solutions = args[1].sympify()
            symbol = default_symbol(solutions[0] - solutions[2])
            solutions_interval = answer_intervalSingle(symbol, solutions[1], solutions[2])
            answers = []
            for i, ineq in enumerate(ineqs, 1):
                res = jiebudengshi_Parameter().solver(BaseIneq(ineq)).output[0]
                answer = res.value[symbol]
                answers.append(answer)
                self.steps.append(["由(%d)得" % i, self.output_answer({symbol: answer})])
            if answers[0] != solutions_interval and answers[1] != solutions_interval:
                answer0_left, answer0_right, answer0_lopen, answer0_ropen = answers[0].args
                answer1_left, answer1_right, answer1_lopen, answer1_ropen = answers[1].args
                solutions_left, solutions_right, solutions_lopen, solutions_ropen = solutions_interval.args
                if not (answer0_left == answer1_left and answer1_left == solutions_left):
                    if solutions_left.is_Number:
                        if answer0_left.is_Number and not answer1_left.is_Number and (
                                solutions_right.is_Number != answer0_left.is_Number):
                            eq_left = [answer1_left, solutions_right]
                            self.output.append(BaseEq(eq_left))
                            self.steps.append(
                                ["因为不等式组的解集是%s，所以：" % new_latex(Rel(solutions[0], solutions[2],
                                                                                solutions[1])),
                                 self.output_eq(eq_left)])
                        elif answer1_left.is_Number and not answer0_left.is_Number and (
                                solutions_right.is_Number != answer1_left.is_Number):
                            eq_left = [answer0_left, solutions_right]
                            self.output.append(BaseEq(eq_left))
                            self.steps.append(
                                ["因为不等式组的解集是%s，所以：" % new_latex(Rel(solutions[0], solutions[2],
                                                                                solutions[1])),
                                 self.output_eq(eq_left)])
                elif not (answer0_right == answer1_right and answer1_right == solutions_right):
                    if solutions_right.is_Number:
                        if answer0_right.is_Number and not answer1_right.is_Number and (
                                solutions_right != answer0_right):
                            eq_right = [answer1_right, solutions_right]
                            self.output.append(BaseEq(eq_right))
                            self.steps.append(
                                ["因为不等式组的解集是%s，所以：" % new_latex(Rel(solutions[0], solutions[2],
                                                                                solutions[1])),
                                 self.output_eq(eq_right)])
                        elif answer1_right.is_Number and not answer0_right.is_Number and (
                                solutions_right != answer1_right):
                            eq_right = [answer0_right, solutions_right]
                            self.output.append(BaseEq(eq_right))
                            self.steps.append(
                                ["因为不等式组的解集是%s，所以：" % new_latex(Rel(solutions[0], solutions[2],
                                                                                solutions[1])),
                                 self.output_eq(eq_right)])
                        elif not answer0_right.is_Number and not answer1_right.is_Number:
                            first_ineqs = [[answer0_right, "<=", answer1_right], [answer0_right, solutions_right]]
                            stepsolver1 = FangChenBuDengShi002().solver(base_gen(first_ineqs))
                            first_jies = stepsolver1.output[0].value
                            second_ineqs = [[answer0_right, ">", answer1_right], [answer1_right, solutions_right]]
                            stepsolver2 = FangChenBuDengShi002().solver(base_gen(second_ineqs))
                            second_jies = stepsolver2.output[0].value
                            self.steps.append(["", "下面分两种情况来讨论"])
                            if not first_jies[first_jies.keys()[0]].args:
                                self.steps.append(
                                    ["", "情况一：%s %s %s 且 %s %s %s" % (new_latex(answer0_right), new_latex("<="),
                                                                          new_latex(answer1_right),
                                                                          new_latex(answer0_right),
                                                                          new_latex("="),
                                                                          new_latex(solutions_right))])
                                self.output.append(base_gen(first_ineqs))
                            else:
                                self.steps.append(
                                    ["", "情况二：%s %s %s 且 %s %s %s" % (new_latex(answer0_right), new_latex("<="),
                                                                          new_latex(answer1_right),
                                                                          new_latex(answer0_right),
                                                                          new_latex("="),
                                                                          new_latex(solutions_right))])
                                self.output.append(base_gen(first_ineqs))
                            if not second_jies[second_jies.keys()[0]].args:
                                self.steps.append(
                                    ["", "情况二：%s %s %s 且 %s %s %s" % (new_latex(answer0_right), new_latex(">"),
                                                                          new_latex(answer1_right),
                                                                          new_latex(answer1_right),
                                                                          new_latex("="),
                                                                          new_latex(solutions_right))])
                                self.output.append(base_gen(second_ineqs))
                            else:
                                self.steps.append(
                                    ["", "情况一：%s %s %s 且 %s %s %s" % (new_latex(answer0_right), new_latex(">"),
                                                                          new_latex(answer1_right),
                                                                          new_latex(answer1_right),
                                                                          new_latex("="),
                                                                          new_latex(solutions_right))])
                                self.output.append(base_gen(second_ineqs))
            else:
                for answer in answers:
                    if answer != solutions_interval:
                        answer_left, answer_right, answer_lopen, answer_ropen = answer.args
                        solutions_left, solutions_right, solutions_lopen, solutions_ropen = solutions_interval.args
                        if solutions_left.is_infinite and answer_left.is_infinite:
                            if answer_ropen and not solutions_ropen:
                                ineq = [answer_right, ">", solutions_right]
                            else:
                                ineq = [answer_right, ">=", solutions_right]
                        elif solutions_right.is_infinite and answer_right.is_infinite:
                            if answer_lopen and not solutions_lopen:
                                ineq = [answer_left, "<", solutions_left]
                            else:
                                ineq = [answer_left, "<=", solutions_left]
                        self.steps.append(["因为不等式组的解集是%s，所以：" % new_latex(Rel(solutions[0], solutions[2],
                                                                                          solutions[1])),
                                           self.output_eq(ineq)])
                        self.output.append(BaseIneq(ineq))
        self.label.add("根据含参的一元一次不等式组的解集求参")
        return self


class FangChenBuDengShi005(BaseFunction):
    """
    不等式mx-2<3x+4的解集是x>\\frac{6}{m-3},则m的取值范围是.
    """
    def solver(self, *args):
        ineq = args[0].sympify()
        jieji = args[1].sympify()
        f = ineq[0] - ineq[2]
        symbol = default_symbol(f)
        assert yicifangcheng_judge(f, symbol)
        a, h = f.as_independent(symbol)
        h_factor = h.factor()
        f11 = h_factor
        op1 = ineq[1]
        f12 = - a
        f21 = jieji[0]
        op2 = jieji[1]
        f22 = jieji[2]
        ineq = Rel(f11, f12, op1)
        new_answer = Rel(f21, f22, op2)

        if (f11 / x) * f22 == f12:
            if op1 == op2:
                new_ineq = [f11 / x, ">", S.Zero]
            else:
                new_ineq = [f11 / x, "<", S.Zero]
            self.steps.append(["", "因为不等式%s的解集是%s, " % (new_latex(ineq), new_latex(new_answer))])
            self.steps.append(["", "所以：%s " % self.output_eq(new_ineq)])
            self.output.append(BaseIneq(new_ineq))
        elif f22.is_Number:
            symbol = default_symbol(f21 - f22)
            f1 = f11.subs({symbol: f22})
            f2 = f12.subs({symbol: f22})
            self.steps.append(["", "因为不等式%s的解集是%s, " % (new_latex(ineq), new_latex(new_answer))])
            self.steps.append(["所以", BaseEq([f1, f2]).printing()])
            self.output.append(BaseEq([f1, f2]))
        return self


class FangChenBuDengShi006(BaseFunction):
    """
    含参不等式组有解问题
    """
    def solver(self, *args):
        ineqs = args[0].sympify()
        symbol = x
        answers = []
        small = None
        large = None
        left_op = None
        right_op = None
        for i, ineq in enumerate(ineqs, 1):
            res = jiebudengshi_Parameter().solver(BaseIneq(ineq)).output[0]
            answer = res.value[symbol]
            answers.append(answer)
            self.steps.append(["由(%d)得" % i, self.output_answer({symbol: answer})])
            l, r, lopen, ropen = answer.args
            smaller_op = {False: "<=", True: "<"}
            larger_op = {False: ">=", True: ">"}
            if l.is_infinite:
                large = r
                right_op = smaller_op[ropen]
            else:
                small = l
                left_op = larger_op[lopen]
        assert small is not None and large is not None
        assert left_op is not None and right_op is not None
        if left_op == right_op:
            ineq = [small, "<=", large]
        else:
            ineq = [small, "<", large]

        self.steps.append(["因为不等式组有解集，所以：", self.output_eq(ineq)])
        self.output.append(BaseIneq(ineq))
        self.label.add("含参不等式组有解问题")
        return self


class FangChenBuDengShi008(BaseFunction):
    """
    根据一元一次不等式的正整数解的个数求参
    """
    def solver(self, *args):
        ineq = args[0].sympify()
        numbers = args[1].sympify()
        numbers_max = max(numbers)
        stepsolver = jiebudengshi_Parameter(verbose=True).solver(BaseIneq(ineq))
        self.append(stepsolver)
        self.steps.append(["因为不等式的正整数解恰是", BaseNumber(numbers).printing()])
        jie = stepsolver.output[0].value
        answer = jie[jie.keys()[0]]
        answer_left, answer_right, answer_lopen, answer_ropen = answer.args
        if answer_ropen:
            ineqs = [[numbers_max, "<", answer_right], [answer_right, "<", numbers_max + 1]]
            self.steps.append(["所以", BaseIneqs(ineqs).printing()])
            self.output.append(BaseIneqs(ineqs))
        else:
            ineqs = [[numbers_max, "<=", answer_right], [answer_right, "<", numbers_max + 1]]
            self.steps.append(["所以", BaseIneqs(ineqs).printing()])
            self.output.append(BaseIneqs(ineqs))
        return self


class YiYuanYiCiBuDengShiDingYi(BaseFunction):
    """
    一元一次不等式的定义
    """
    def solver(self, *args):
        f1, op, f2 = args[0].sympify()
        eq = [f1, f2]
        stepsolver = YiCi005(verbose=True).solver(BaseEq(eq))
        eqs = stepsolver.output[0].value
        if len(eqs) == 2:
            self.steps.append(["根据题意，得", self.output_eq(eqs)])
        else:
            self.steps.append(["根据题意，得", self.output_eqs(eqs)])
        self.output.append(base_gen(eqs))
        self.label.add("一元一次不等式的定义")
        return self


class FangChengBuDengShi009(BaseFunction):
    """
    已知不等式4x-a≤0的正整数解是1,2,则a的取值范围是.
    """
    def solver(self, *args):
        if isinstance(args[0], BaseSymbolValue):
            jies = args[0].sympify()
            jies_interval = jies[jies.keys()[0]]
        jies_number = args[1].sympify()
        l, r, lopen, ropen = jies_interval.args
        if l.is_infinite and not r.is_infinite:
            if ropen:
                ineqs = [jies_number[-1], "<", r, "<", jies_number[-1] + 1]
                self.steps.append(["∴", BaseIneqs(ineqs).printing()])
                self.output.append(BaseIneqs(ineqs))
            else:
                ineqs = [jies_number[-1], "<=", r, "<", jies_number[-1] + 1]
                self.steps.append(["∴", BaseIneqs(ineqs).printing()])
                self.output.append(BaseIneqs(ineqs))
        return self


class FangChengBuDengShi010(BaseFunction):
    """
    如果关于x,y的方程组eqs的解满足x-y>0,求m的取值范围.
    """
    def solver(self, *args):
        if isinstance(args[0], BaseSymbolValue):
            answers = args[0].sympify()
            answers_keys = answers.keys()
            if len(answers_keys) == 2:
                subs = {answers_keys[0]: answers[answers_keys[0]].args[0],
                        answers_keys[1]: answers[answers_keys[1]].args[0]}
            elif len(answers_keys) == 1:
                subs = {answers_keys[0]: answers[answers_keys[0]].args[0]}
        ineq = args[1].sympify()
        new_ineq_left = ineq[0].subs(subs)
        new_ineq_right = ineq[2].subs(subs)
        self.steps.append(["代入不等式，得", BaseIneq([new_ineq_left, ineq[1], new_ineq_right]).printing()])
        self.output.append(BaseIneq([new_ineq_left, ineq[1], new_ineq_right]))
        return self


if __name__ == '__main__':
    pass
